import ij._
import ij.ImagePlus._
import ij.process._
import ij.process.ImageProcessor._
import de.latzko.pattern.collections._
import de.latzko.pattern.collections.GenCell
import java.util.ArrayList._
import scalala.Scalala._;
import scalala.tensor.{ Tensor, Tensor1, Tensor2, Vector, Matrix };
import scalala.tensor.dense.{ DenseVector, DenseMatrix };
import scalala.tensor.sparse._;
import de.latzko.pattern.math._;
import de.latzko.pattern.monteCarlo._;

object Main {

  def main(args: Array[String]): Unit = {
		 
    val n = 500
    var arr = testSet2(n)
 
    // scatterPlot(arr)
    val nn = new SwendsenWang(arr, 20, 8)
    val n2 = new Wolff(arr, 20, 11)
    val times = 200
    var chi = DenseVector(times)(0)
    var chi2 = DenseVector(times)(0)
    var tArr = DenseVector(times)(0)
    //nn.runMethode(500, 0.2)
    var T = 0.001
    var t = System.currentTimeMillis()
   t = System.currentTimeMillis()
    //var susc = SpmCluster.apply(1000, arr, 20, 11, 0.5,times)
    println("\n parallel montecarlo tempstep: " + (System.currentTimeMillis() - t))

    println("start monte carlo method")
    for (i <- 0 until times) {

      t = System.currentTimeMillis()
     // chi(i) = nn.runMethode(500, T) * T / n
      println("\n montecarlo tempstep: " + (System.currentTimeMillis() - t))
    	//susc(i) = susc(i) * T / n
      t = System.currentTimeMillis()
      chi2(i) = n2.runMethode(4000, T) * T / n
      println("\n Wolff tempstep: " + (System.currentTimeMillis() - t))
      tArr(i) = T
      T += 0.001
      println(T)


    }
           figure(1)
//      plot(tArr, chi,'.')
//      hold(true)
      plot(tArr, chi2,'.')
//      hold(false)

  }

  def testSet1(n: Int, noise: Double = 10): Array[DenseVector] = {
    val n2: Int = n / 2;
    var arr = new Array[DenseVector](n);

    for (i <- 0 until n2) {

      arr(i) = Vector(math.random, math.random)
    }
    for (i <- n2 until n) {

      arr(i) = Vector(math.random * noise - noise / 2, math.random * noise - noise / 2)
    }
    return arr;
  }

  def testSet2(n: Int, innerRadius: Double = 2, outRadius: Double = 2.3): Array[DenseVector] = {
    val n2: Int = n / 3;
    var arr = new Array[DenseVector](n);

    //inner circle with radius 1
    for (i <- 0 until n2) {
      val phi = math.random * 2 * math.Pi
      val r = math.random
      val x = math.cos(phi) * r
      val y = math.sin(phi) * r
      arr(i) = Vector(x, y)
    }
    
    //square noise
    val noise = 3 * outRadius
    for (i <- n2 until 2 * n2) {
      arr(i) = Vector(math.random * noise - noise / 2, math.random * noise - noise / 2)
    }

    //outer ring
    for (i <- 2 * n2 until n) {
      val phi = math.random * 2 * math.Pi
      val r = math.random * (outRadius - innerRadius) + innerRadius
      val x = math.cos(phi) * r
      val y = math.sin(phi) * r
      arr(i) = Vector(x, y)
    }
    return arr;
  }

  def scatterPlot(arr: Array[DenseVector]) = {
    val n = arr.size;
    var x = DenseVector(n)(0)
    var y = DenseVector(n)(0)
    var c = DenseVector(n)(0)
    var s = DenseVector(n)(0.02)
    for (i <- 0 until n) {
      x(i) = arr(i)(0); y(i) = arr(i)(1);
      c(i) = math.random
    }
    scatter(x, y, s, c)

  }
}
